using System.Collections.Generic;
using System.IO;
using Sixeyed.CodeGeneration.Metadata.Bases;
using Sixeyed.CodeGeneration.Metadata.FileSystem.Interfaces;

namespace Sixeyed.CodeGeneration.Metadata.FileSystem
{
    /// <summary>
    /// Abstract base class for file system sources
    /// </summary>
    public abstract class FileSystemSource : SourceBase, IFileSystemSource
    {
        private DirectoryInfo _rootDirectory;

        /// <summary>
        /// Gets the type of the source
        /// </summary>
        public override string SourceTypeName
        {
            get { return "File System"; }
        }

        /// <summary>
        /// Gets the display name for source Uri
        /// </summary>
        public override string UriDisplayName
        {
            get { return "Root Directory"; }
        }

        /// <summary>
        /// Root directory path used as source Uri
        /// </summary>
        public override string Uri
        {
            get { return base.Uri; }
            set
            {
                if (base.Uri != value)
                {
                    base.Uri = value;
                    this._rootDirectory = null;
                }
            }
        }

        /// <summary>
        /// Gets the root directory
        /// </summary>
        protected DirectoryInfo RootDirectory
        {
            get
            {
                if (this._rootDirectory == null)
                {
                    this._rootDirectory = new DirectoryInfo(this.Uri);
                }
                return this._rootDirectory;
            }
        }

        /// <summary>
        /// Gets a list of files under the root directory
        /// </summary>
        /// <param name="filter">File name filter to match against</param>
        /// <returns>List of matching files</returns>
        public List<string> GetFileList(string filter)
        {
            FileInfo[] files = this.RootDirectory.GetFiles(filter);
            List<string> fileList = new List<string>(files.Length);
            foreach (FileInfo file in files)
            {
                fileList.Add(file.Name);
            }
            return fileList;
        }

        /// <summary>
        /// Gets the string contents of the given file
        /// </summary>
        /// <param name="path">Path of file to load</param>
        /// <returns>File contents</returns>
        public string GetFileContent(string path)
        {
            return File.ReadAllText(Path.Combine(this.Uri, path));
        }

        /// <summary>
        /// Gets a list of directories under the root directory
        /// </summary>
        /// <returns>Directory list</returns>
        public List<string> GetDirectoryList()
        {
            //REFACTOR - items should have display name (dir.Name) and key (dir.FullName)
            DirectoryInfo[] directories = this.RootDirectory.GetDirectories();
            List<string> directoryList = new List<string>(directories.Length);
            foreach (DirectoryInfo directory in directories)
            {
                directoryList.Add(directory.FullName);
            }
            return directoryList;
        }

        /// <summary>
        /// Gets a list of file infos for a given directory
        /// </summary>
        /// <param name="path">Directory to list</param>
        /// <returns>File list</returns>
        public List<FileInfo> GetFileInfoList(string path)
        {
            path = Path.Combine(this.Uri, path);
            DirectoryInfo info = new DirectoryInfo(path);
            FileInfo[] files = info.GetFiles();
            List<FileInfo> infos = new List<FileInfo>(files.Length);
            infos.AddRange(files);
            return infos;
        }
    }
}
